package ro.tm.uvt.lp.raccoon.catchGame.entities.agents;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import ro.tm.uvt.lp.raccoon.catchGame.entities.Agent;
import ro.tm.uvt.lp.raccoon.catchGame.entities.agents.actions.RaccoonSniffCookieDown;
import ro.tm.uvt.lp.raccoon.catchGame.entities.agents.actions.RaccoonSniffCookieLeft;
import ro.tm.uvt.lp.raccoon.catchGame.entities.agents.actions.RaccoonSniffCookieRight;
import ro.tm.uvt.lp.raccoon.catchGame.entities.agents.actions.RaccoonSniffCookieUp;
import ro.tm.uvt.lp.raccoon.catchGame.entities.agents.actions.RaccoonSniffDogDown;
import ro.tm.uvt.lp.raccoon.catchGame.entities.agents.actions.RaccoonSniffDogLeft;
import ro.tm.uvt.lp.raccoon.catchGame.entities.agents.actions.RaccoonSniffDogRight;
import ro.tm.uvt.lp.raccoon.catchGame.entities.agents.actions.RaccoonSniffDogUp;
import ro.tm.uvt.lp.raccoon.catchGame.entities.perceptions.RaccoonOdor;
import ro.tm.uvt.lp.raccoon.catchGame.entities.physicalObjects.Burrow;
import ro.tm.uvt.lp.raccoon.catchGame.entities.physicalObjects.Food;
import ro.tm.uvt.lp.raccoon.catchGame.entities.physicalObjects.NatureStaticEntity;
import ro.tm.uvt.lp.raccoon.catchGame.environment.Environment;
import ro.tm.uvt.lp.raccoon.catchGame.environment.RaccoonDied;
import ro.tm.uvt.lp.raccoon.catchGame.utils.RandomIntGenerator;

/**
 * Created by user on 1/14/2015.
 */
public class Raccoon extends Agent {


    private RaccoonDied listener = Environment.INSTANCE;

    private boolean changeMove = true;
    private Vector2 velocity = new Vector2();
    private float oldX, oldY;
    private boolean alive = true;
    private boolean safe = false;
    private BitmapFont font, fontEnd;
    private int memoryDirection = -1;


    private List<RaccoonOdor> odor = new ArrayList<RaccoonOdor>();


    private int cookiesEaten = 0;

    public Raccoon(Sprite sprite, int x, int y) {
        super(sprite);

        this.setPosition(x, y);

        RaccoonOdor ro0 = new RaccoonOdor(new Sprite(new Texture("entities/rpaw40.png")));
        ro0.setPosition(getX(), getY());
        this.addOdor(ro0);

        RaccoonOdor ro1 = new RaccoonOdor(new Sprite(new Texture("entities/rpaw40.png")));
        ro1.setPosition(getX(), getY() + Environment.INSTANCE.getTileHeight());
        this.addOdor(ro1);

        RaccoonOdor ro2 = new RaccoonOdor(new Sprite(new Texture("entities/rpaw40.png")));
        ro2.setPosition(getX() + Environment.INSTANCE.getTileWidth(), getY());
        this.addOdor(ro2);

        RaccoonOdor ro3 = new RaccoonOdor(new Sprite(new Texture("entities/rpaw40.png")));
        ro3.setPosition(getX(), getY() - Environment.INSTANCE.getTileHeight());
        this.addOdor(ro3);

        RaccoonOdor ro4 = new RaccoonOdor(new Sprite(new Texture("entities/rpaw40.png")));
        ro4.setPosition(getX() - Environment.INSTANCE.getTileWidth(), getY());
        this.addOdor(ro4);

        font = new BitmapFont();
        fontEnd = new BitmapFont();
        fontEnd.scale(2);
    }


    private void addOdor(RaccoonOdor ro) {
        this.odor.add(ro);
    }

    public List<RaccoonOdor> getOdor() {
        return this.odor;
    }


    @Override
    public void draw(Batch spriteBatch) {
        update(Gdx.graphics.getDeltaTime());

        font.draw(spriteBatch, "Cookies eaten: " + cookiesEaten, 0, 480);
        if (!this.alive) {
            fontEnd.draw(spriteBatch, "The Raccoon has died!", 20, 200);
        }
        if (this.safe) {
            fontEnd.draw(spriteBatch, "The Raccoon is safe in the burrow!", 20, 200);
        }
        super.draw(spriteBatch);
    }

    public void update(float delta) {


        if (changeMove) {

            oldX = getX();
            oldY = getY();

            for (RaccoonOdor ro : odor) {
                ro.setOldX((int) ro.getX());
                ro.setOldY((int) ro.getY());
            }

            //check all 4 directions is any of them is of interest
            //and can be followed by smell
            //if none can be found then go random

            memoryDirection = chooseDirection();

            switch (memoryDirection) {
                case 1:
                    velocity.x = 0;
                    velocity.y = 40;

                    changeMove = false;
                    break;
                case 2:
                    velocity.x = 40;
                    velocity.y = 0;

                    changeMove = false;
                    break;

                case 3:
                    velocity.x = 0;
                    velocity.y = -40;

                    changeMove = false;
                    break;

                case 4:
                    velocity.x = -40;
                    velocity.y = 0;

                    changeMove = false;
                    break;
            }
        }

//        boolean collisionX = false;
//        boolean collisionY = false;

        // move on x
        setX(getX() + velocity.x * delta);
        for (RaccoonOdor ro : odor) {
            ro.setX(ro.getX() + velocity.x * delta);
        }
        setY(getY() + velocity.y * delta);
        for (RaccoonOdor ro : odor) {
            ro.setY(ro.getY() + velocity.y * delta);
        }

        //move up and down
        if (getX() == oldX && (getY() >= oldY + 40 || getY() <= oldY - 40))
            changeMove = true;

        //move left and right
        if (getY() == oldY && (getX() >= oldX + 40 || getX() <= oldX - 40))
            changeMove = true;


        //collides with nature
        if (collidesWithNature()) {
            velocity.x = 0;
            velocity.y = 0;
            setX(oldX);
            setY(oldY);
            for (RaccoonOdor ro : odor) {
                ro.setX(ro.getOldX());
                ro.setY(ro.getOldY());
            }

            changeMove = true;
        }
        collidesWithFood();
        collidesWithBurrow();
        collideWithDogs();
//
        //collides with limits / stay within limits
        //deal with the odor
        collidesWithLeftLimit();
        collidesWithRightLimit();
        collidesWithUpperLimit();
        collidesWithBottomLimit();


    }



    private boolean collidesWithNature() {
        for (NatureStaticEntity nse : Environment.INSTANCE.getNature()) {
//            Rectangle rectangleFood=new Rectangle(nse.getX(),nse.getY(),40,40);
            Rectangle rectangleCurr = new Rectangle(getX(), getY(), Environment.INSTANCE.getTileWidth(), Environment.INSTANCE.getTileHeight());
            if (rectangleCurr.overlaps(nse.getBoundingRectangle())) return true;
        }
        return false;
    }


    private void collidesWithFood() {
        Iterator<Food> it = Environment.INSTANCE.getFoods().iterator();
        while (it.hasNext()) {
            Food food = it.next();
//            Rectangle rectangleFood=new Rectangle(food.getX(),food.getY(),40,40);
            Rectangle rectangleCurr = new Rectangle(getX(), getY(), Environment.INSTANCE.getTileWidth(), Environment.INSTANCE.getTileHeight());
            if (rectangleCurr.overlaps(food.getBoundingRectangle())) {
                Environment.INSTANCE.deleteFoodCell(food);
                it.remove();
                cookiesEaten++;
            }
        }
    }

    private void collidesWithBurrow() {

        Burrow burrow = Environment.INSTANCE.getBurrow();
//            Rectangle rectangleBurrow=new Rectangle(burrow.getX(),burrow.getY(),40,40);
        Rectangle rectangleCurr = new Rectangle(getX(), getY(), Environment.INSTANCE.getTileWidth(), Environment.INSTANCE.getTileHeight());
        if (rectangleCurr.overlaps(burrow.getBoundingRectangle())) {
            listener.died();
            this.safe = true;
        }
    }

    private void collideWithDogs() {
        for (Dog dog : Environment.INSTANCE.getDogs()) {
//            Rectangle rectangleDog=new Rectangle(dog.getX(),dog.getY(),40,40);
            Rectangle rectangleCurr = new Rectangle(getX(), getY(), Environment.INSTANCE.getTileWidth(), Environment.INSTANCE.getTileHeight());
            if (rectangleCurr.overlaps(dog.getBoundingRectangle())) {
                listener.died();
                this.alive = false;
            }
        }
    }

    private void collidesWithLeftLimit(){
        if (getX() < 0) {
            float x=0;
            setX(x);
            velocity.x = 0;
            velocity.y = 0;
            this.odor.get(0).setPosition(getX(), getY());
            this.odor.get(1).setPosition(getX(), getY() + Environment.INSTANCE.getTileHeight());
            this.odor.get(2).setPosition(getX() + Environment.INSTANCE.getTileWidth(), getY());
            this.odor.get(3).setPosition(getX(), getY() - Environment.INSTANCE.getTileHeight());
            this.odor.get(4).setPosition(getX()-Environment.INSTANCE.getTileWidth(), getY());

            changeMove = true;
        }
    }

    private void collidesWithRightLimit(){
        if (getX() > Environment.INSTANCE.getWidth() - Environment.INSTANCE.getTileWidth()) {
            float x= Environment.INSTANCE.getWidth() - Environment.INSTANCE.getTileWidth();
            setX(x);
            velocity.x = 0;
            velocity.y = 0;
            this.odor.get(0).setPosition(getX(), getY());
            this.odor.get(1).setPosition(getX(), getY() + Environment.INSTANCE.getTileHeight());
            this.odor.get(2).setPosition(getX() + Environment.INSTANCE.getTileWidth(), getY());
            this.odor.get(3).setPosition(getX(), getY() - Environment.INSTANCE.getTileHeight());
            this.odor.get(4).setPosition(getX()-Environment.INSTANCE.getTileWidth(), getY());
            changeMove = true;
        }
    }

    private void collidesWithUpperLimit(){
        if (getY() > Environment.INSTANCE.getHeight() - Environment.INSTANCE.getTileHeight()) {
            float y=Environment.INSTANCE.getHeight() - Environment.INSTANCE.getTileHeight();
            setY(y);
            velocity.x = 0;
            velocity.y = 0;
            this.odor.get(0).setPosition(getX(), getY());
            this.odor.get(1).setPosition(getX(), getY() + Environment.INSTANCE.getTileHeight());
            this.odor.get(2).setPosition(getX() + Environment.INSTANCE.getTileWidth(), getY());
            this.odor.get(3).setPosition(getX(), getY() - Environment.INSTANCE.getTileHeight());
            this.odor.get(4).setPosition(getX()-Environment.INSTANCE.getTileWidth(), getY());
            changeMove = true;
        }
    }

    private void collidesWithBottomLimit(){
        if (getY() < 0) {
            float y= 0;
            setY(y);
            velocity.x = 0;
            velocity.y = 0;
            this.odor.get(0).setPosition(getX(), getY());
            this.odor.get(1).setPosition(getX(), getY() + Environment.INSTANCE.getTileHeight());
            this.odor.get(2).setPosition(getX() + Environment.INSTANCE.getTileWidth(), getY());
            this.odor.get(3).setPosition(getX(), getY() - Environment.INSTANCE.getTileHeight());
            this.odor.get(4).setPosition(getX()-Environment.INSTANCE.getTileWidth(), getY());
            changeMove = true;
        }
    }


    public void resetVelocity() {
        this.velocity.x = 0;
        this.velocity.y = 0;
    }

    private int chooseDirection() {
        if (new RaccoonSniffCookieUp().sniff(getX(), getY()) && !new RaccoonSniffDogUp().sniff(getX(),getY()))
            return 1;
        else if (new RaccoonSniffCookieRight().sniff(getX(), getY()) && !new RaccoonSniffDogRight().sniff(getX(),getY()))
            return 2;
        else if (new RaccoonSniffCookieDown().sniff(getX(), getY()) && !new RaccoonSniffDogDown().sniff(getX(),getY()))
            return 3;
        else if (new RaccoonSniffCookieLeft().sniff(getX(), getY()) && !new RaccoonSniffDogLeft().sniff(getX(),getY()))
            return 4;
        else {
            int direction, newX = (int) oldX, newY = (int) oldY;
            int count = 0;
            do {
                direction = RandomIntGenerator.randInt(1, 4);
                count++;
                switch (direction) {
                    case 1:
                        newX = (int) oldX;
                        newY = (int) (40 + oldY);


                        break;
                    case 2:
                        newX = (int) (oldX + 40);
                        newY = (int) oldY;


                        break;

                    case 3:
                        newX = (int) oldX;
                        newY = (int) (oldY - 40);


                        break;

                    case 4:
                        newX = (int) (oldX - 40);
                        newY = (int) oldY;


                        break;
                }

            }
            while (new Rectangle(newX, newY, 40, 40).overlaps(new Rectangle(oldX, oldY, 40, 40)) && count < 4);
            return direction;
        }
    }

}
